#include "CardPort.h"
#include "CardPort.h"

#include <stddef.h>
#include "CardController.h"
#include "CardPort.h"
#include "CardPortPrivate.h"
#include "CardPrivate.h"
#include "CardCpu.h"
#include "CardMem.h"
#include "CardMemPrivate.h"

#include "Contactless/ISO14443p3a.h"

static CardPort* cardPorts[Port_Index_Max];

#if 0
static int CardPort_FindFreePos(CardPort* port) 
{
	int i;
	for (i = 0; i < port->maxCard; i++) {
		if (!port->card[i]){
			return i;
		}
	}
	return -1;
}
#endif 

void CardPort_Register(CardPort* port, int index) 
{
	REQUIRE(index < Port_Index_Max);
	if (index < Port_Index_Max) {
		cardPorts[index] = port;
	}
}
int CardPort_Picc_SetRf(uint8_t index, uint8_t state)
{	
	REQUIRE(index < Port_Index_Max);
	REQUIRE(cardPorts[index]);
	return WCI_Config((WCI*)(cardPorts[index]->pdata), state ? WCI_Cfg_RfOn : WCI_Cfg_RfOff);
}


int CardPort_Picc_Detect(uint8_t index, uint8_t type)
{
//		int pos;
	CardPort* port;

	REQUIRE(index < Port_Index_Max);
	REQUIRE(cardPorts[index]);

	port = cardPorts[index];
	if (!(port->typeMask & (1 << type))){
		return 0;
	}
	return Controller_Detect((WCI*)port->pdata, type);
}


int CardPort_Picc_Activate(uint8_t index, uint8_t type, uint8_t req, void* info)
{
	REQUIRE(index < Port_Index_Max);
	REQUIRE(cardPorts[index]);
	return Controller_Activate((WCI*)cardPorts[index]->pdata, type, req, info);
}


int CardPort_Picc_Setup(uint8_t index, uint8_t num, uint8_t type, void* param, uint8_t ats[])
{
	CardPort* port;
	int ret;
	Card_T* card;
	
	REQUIRE(index < Port_Index_Max);
	REQUIRE(cardPorts[index]);

	port = cardPorts[index];
	card = Card_CPU_Create((WCI*)port->pdata, type);
	ret = Card_CPU_Setup(card, num, 8, param, ats);
	if(ret){
		Card_CPU_Destroy(card);
		return ret;
	}
	port->card[num] = card;
	return ret;
}

int CardPort_Picc_Teardown(uint8_t index, uint8_t num)
{
	REQUIRE(index < Port_Index_Max);
	REQUIRE(cardPorts[index]);

	return Card_CPU_Teardown(cardPorts[index]->card[num]);
}

int CardPort_Picc_Exchange(uint8_t index, uint8_t num, uint8_t capdu[], unsigned int clen, uint8_t rapdu[], unsigned int * rlen)
{
	REQUIRE(index < Port_Index_Max);
	REQUIRE(cardPorts[index]);

	return Card_CPU_Exchange(cardPorts[index]->card[num], capdu, clen, rapdu, rlen);
}

int CardPort_Picc_Deactivate(uint8_t index, uint8_t num) 
{
	REQUIRE(index < Port_Index_Max);
	REQUIRE(cardPorts[index]);

	return Card_CPU_Deactivate(cardPorts[index]->card[num]);
}

int CardPort_Picc_Destroy(uint8_t index, uint8_t num)
{
	REQUIRE(index < Port_Index_Max);
	REQUIRE(cardPorts[index]);
	Card_T* card = cardPorts[index]->card[num];
	if(card->type < Card_T_CpuMax){
		Card_CPU_Destroy(card);
	}
	else
	if(card->type < Card_T_MemMax){
		Card_Mem_Destroy(card);
	}
	else{
		return -1;
	}
	cardPorts[index]->card[num] = (Card_T*)0;
	return 0;
}

int CardPort_Picc_Check(uint8_t index, uint8_t num){
	REQUIRE(index < Port_Index_Max);
	REQUIRE(cardPorts[index]);
	
	Card_T* card = cardPorts[index]->card[num];
	return Card_CPU_Check(card);
}


int CardPort_PMem_Setup(uint8_t index, uint8_t num, uint8_t type, void* param){
	CardPort* port;
	int ret;
	Card_T* card;
	
	REQUIRE(index < Port_Index_Max);
	REQUIRE(cardPorts[index]);

	port = cardPorts[index];
	card = Card_Mem_Create((WCI*)port->pdata, type);
	ret = Card_Mem_Setup(card, param);
	if(ret){
		Card_Mem_Destroy(card);
		return ret;
	}
	port->card[num] = card;
	return ret;

}

int CardPort_PMem_Authen(uint8_t index, uint8_t num, void* param, uint8_t* key, uint8_t klen){
	REQUIRE(index < Port_Index_Max);
	REQUIRE(cardPorts[index]);
	return Card_Mem_Authen(cardPorts[index]->card[num],  param, key,  klen);
}

int CardPort_PMem_Read(uint8_t index, uint8_t num, uint16_t address, uint8_t* buf, uint16_t len){
	REQUIRE(index < Port_Index_Max);
	REQUIRE(cardPorts[index]);
	return Card_Mem_Read(cardPorts[index]->card[num], address, buf, len);
}

int CardPort_PMem_Write(uint8_t index, uint8_t num, uint16_t address, uint8_t* buf, uint16_t len){
	REQUIRE(index < Port_Index_Max);
	REQUIRE(cardPorts[index]);
	
	return Card_Mem_Write(cardPorts[index]->card[num], address, buf, len);
}

int CardPort_PMem_Control(uint8_t index, uint8_t num, uint8_t op, void* param, 
	void* cbuf, uint16_t clen, void* rbuf, uint16_t* rlen){
	REQUIRE(index < Port_Index_Max);
	REQUIRE(cardPorts[index]);
	
	return Card_Mem_Control(cardPorts[index]->card[num], op, param, cbuf, clen, rbuf, rlen);
}


